package com.markdownviewer;

import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Optional;

/**
 * 主控制器类，处理用户界面交互和Markdown渲染
 */
public class MainController {

    @FXML
    private TextArea markdownTextArea;
    
    @FXML
    private WebView previewWebView;
    
    @FXML
    private Label statusLabel;
    
    @FXML
    private Label filePathLabel;
    
    @FXML
    private CheckMenuItem livePreviewMenuItem;
    
    @FXML
    private ToggleButton livePreviewToggle;
    
    @FXML
    private RadioMenuItem lightThemeMenuItem;
    
    @FXML
    private RadioMenuItem darkThemeMenuItem;
    
    @FXML
    private ToggleButton lightThemeToggle;
    
    @FXML
    private ToggleButton darkThemeToggle;
    
    private Stage primaryStage;
    private File currentFile;
    private Parser markdownParser;
    private HtmlRenderer htmlRenderer;
    private boolean isLivePreviewEnabled = true;
    private boolean isDarkTheme = false;

    /**
     * 初始化控制器
     */
    @FXML
    private void initialize() {
        // 初始化Markdown解析器
        MutableDataSet options = new MutableDataSet();
        options.set(Parser.EXTENSIONS, Arrays.asList(
                TablesExtension.create(),
                StrikethroughExtension.create()
        ));
        markdownParser = Parser.builder(options).build();
        htmlRenderer = HtmlRenderer.builder(options).build();
        
        // 设置文本变化监听器
        ChangeListener<String> textChangeListener = (observable, oldValue, newValue) -> {
            if (isLivePreviewEnabled) {
                renderMarkdown();
            }
        };
        markdownTextArea.textProperty().addListener(textChangeListener);
        
        // 初始化WebView
        previewWebView.getEngine().setUserStyleSheetLocation(
                getClass().getResource("/css/preview-light.css").toExternalForm());
        
        // 设置示例Markdown文本
        markdownTextArea.setText("# Markdown查看器\n\n欢迎使用Markdown查看器！\n\n## 功能特点\n\n* 实时预览\n* 支持表格\n* 支持主题切换\n\n## 使用方法\n\n1. 打开Markdown文件\n2. 编辑内容\n3. 保存文件\n\n> 提示：可以使用工具栏按钮快速操作");
        
        // 初始渲染
        renderMarkdown();
    }
    
    /**
     * 设置主舞台引用
     */
    public void setPrimaryStage(Stage primaryStage) {
        this.primaryStage = primaryStage;
    }
    
    /**
     * 处理打开文件操作
     */
    @FXML
    private void handleOpenFile() {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("打开Markdown文件");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("Markdown文件", "*.md", "*.markdown"),
                new FileChooser.ExtensionFilter("所有文件", "*.*")
        );
        
        File selectedFile = fileChooser.showOpenDialog(primaryStage);
        if (selectedFile != null) {
            try {
                String content = Files.readString(selectedFile.toPath());
                markdownTextArea.setText(content);
                currentFile = selectedFile;
                filePathLabel.setText(selectedFile.getAbsolutePath());
                statusLabel.setText("已打开文件");
            } catch (IOException e) {
                showAlert(Alert.AlertType.ERROR, "错误", "无法打开文件", e.getMessage());
            }
        }
    }
    
    /**
     * 处理保存文件操作
     */
    @FXML
    private void handleSaveFile() {
        if (currentFile == null) {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("保存Markdown文件");
            fileChooser.getExtensionFilters().addAll(
                    new FileChooser.ExtensionFilter("Markdown文件", "*.md"),
                    new FileChooser.ExtensionFilter("所有文件", "*.*")
            );
            
            File selectedFile = fileChooser.showSaveDialog(primaryStage);
            if (selectedFile != null) {
                currentFile = selectedFile;
            } else {
                return; // 用户取消了保存操作
            }
        }
        
        try {
            Files.writeString(currentFile.toPath(), markdownTextArea.getText());
            filePathLabel.setText(currentFile.getAbsolutePath());
            statusLabel.setText("文件已保存");
        } catch (IOException e) {
            showAlert(Alert.AlertType.ERROR, "错误", "无法保存文件", e.getMessage());
        }
    }
    
    /**
     * 处理退出操作
     */
    @FXML
    private void handleExit() {
        if (hasUnsavedChanges()) {
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.setTitle("确认退出");
            alert.setHeaderText("有未保存的更改");
            alert.setContentText("是否要保存更改后退出？");
            
            ButtonType saveButton = new ButtonType("保存");
            ButtonType dontSaveButton = new ButtonType("不保存");
            ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
            
            alert.getButtonTypes().setAll(saveButton, dontSaveButton, cancelButton);
            
            Optional<ButtonType> result = alert.showAndWait();
            if (result.isPresent()) {
                if (result.get() == saveButton) {
                    handleSaveFile();
                    Platform.exit();
                } else if (result.get() == dontSaveButton) {
                    Platform.exit();
                }
                // 如果是取消，什么都不做
            }
        } else {
            Platform.exit();
        }
    }
    
    /**
     * 处理刷新预览操作
     */
    @FXML
    private void handleRefreshPreview() {
        renderMarkdown();
        statusLabel.setText("预览已刷新");
    }
    
    /**
     * 处理实时预览切换操作
     */
    @FXML
    private void handleLivePreviewToggle() {
        isLivePreviewEnabled = livePreviewToggle.isSelected();
        livePreviewMenuItem.setSelected(isLivePreviewEnabled);
        
        if (isLivePreviewEnabled) {
            renderMarkdown();
            statusLabel.setText("实时预览已启用");
        } else {
            statusLabel.setText("实时预览已禁用");
        }
    }
    
    /**
     * 处理主题切换操作
     */
    @FXML
    private void handleThemeChange() {
        // 同步菜单项和按钮状态
        if (lightThemeToggle.isSelected()) {
            lightThemeMenuItem.setSelected(true);
            isDarkTheme = false;
        } else if (darkThemeToggle.isSelected()) {
            darkThemeMenuItem.setSelected(true);
            isDarkTheme = true;
        } else if (lightThemeMenuItem.isSelected()) {
            lightThemeToggle.setSelected(true);
            isDarkTheme = false;
        } else if (darkThemeMenuItem.isSelected()) {
            darkThemeToggle.setSelected(true);
            isDarkTheme = true;
        }
        
        // 应用主题
        applyTheme();
    }
    
    /**
     * 处理关于对话框操作
     */
    @FXML
    private void handleAbout() {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("关于Markdown查看器");
        alert.setHeaderText("Markdown查看器 v1.0");
        alert.setContentText("一个简单的Markdown编辑和预览工具\n\n使用JavaFX和Flexmark开发");
        alert.showAndWait();
    }
    
    /**
     * 渲染Markdown为HTML并显示在预览区域
     */
    private void renderMarkdown() {
        String markdown = markdownTextArea.getText();
        Node document = markdownParser.parse(markdown);
        String html = htmlRenderer.render(document);
        
        // 添加HTML头和样式
        String fullHtml = String.format(
                "<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <style>\n" +
                "        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; }\n" +
                "        pre { background-color: #f5f5f5; padding: 10px; border-radius: 5px; }\n" +
                "        code { font-family: 'Courier New', Courier, monospace; }\n" +
                "        table { border-collapse: collapse; width: 100%%; }\n" +
                "        th, td { border: 1px solid #ddd; padding: 8px; }\n" +
                "        th { background-color: #f2f2f2; }\n" +
                "    </style>\n" +
                "</head>\n" +
                "<body>\n" +
                "%s\n" +
                "</body>\n" +
                "</html>", html);
        
        previewWebView.getEngine().loadContent(fullHtml);
    }
    
    /**
     * 应用主题到界面
     */
    private void applyTheme() {
        String cssPath;
        if (isDarkTheme) {
            cssPath = getClass().getResource("/css/dark-theme.css").toExternalForm();
            previewWebView.getEngine().setUserStyleSheetLocation(
                    getClass().getResource("/css/preview-dark.css").toExternalForm());
            statusLabel.setText("已切换到暗色主题");
        } else {
            cssPath = getClass().getResource("/css/light-theme.css").toExternalForm();
            previewWebView.getEngine().setUserStyleSheetLocation(
                    getClass().getResource("/css/preview-light.css").toExternalForm());
            statusLabel.setText("已切换到亮色主题");
        }
        
        // 应用CSS到场景
        primaryStage.getScene().getStylesheets().clear();
        primaryStage.getScene().getStylesheets().add(getClass().getResource("/css/styles.css").toExternalForm());
        primaryStage.getScene().getStylesheets().add(cssPath);
        
        // 重新渲染Markdown
        renderMarkdown();
    }
    
    /**
     * 检查是否有未保存的更改
     */
    private boolean hasUnsavedChanges() {
        if (currentFile == null) {
            return !markdownTextArea.getText().isEmpty();
        }
        
        try {
            String savedContent = Files.readString(currentFile.toPath());
            return !savedContent.equals(markdownTextArea.getText());
        } catch (IOException e) {
            return true; // 如果无法读取文件，假设有未保存的更改
        }
    }
    
    /**
     * 显示警告对话框
     */
    private void showAlert(Alert.AlertType alertType, String title, String header, String content) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setHeaderText(header);
        alert.setContentText(content);
        alert.showAndWait();
    }
}